# encoding:UTF-8

import turicreate as tc
import pandas as pd
import common as cm
import os
import json


# 表格处理器封装
class TableManager:
    def __init__(self, code):
        self.code = code

    # 输出表格的优化结果
    def copy(self):
        return self.table.copy()

    # 限制价格的变动范围
    def limit(self, table, keys):
        for key in keys:
            table = table[(table[key] > 0.88)&(table[key] < 1.12)]
        return table.copy()

    # 补充参数列表
    @staticmethod
    def fix_parameters():
        result = ['p0']
        bounds = range(1, 9)
        for n in bounds:
            result.append('p' + str(n))
            result.append('diff' + str(n))
            result.append('rate' + str(n))
            result.append('sqr' + str(n))
        return result

    # 移动表格栏, 对source_column进行提取, 然后根据offset进行0轴的偏移, 然后赋值到dest_column
    def shift(self, table, offset, source_column, dest_column):
        if offset == 0:
            return

        list = table.select_column(source_column)
        count = list.shape[0]
        if offset < 0:
            tail = list.tail(count + offset)
            l = [None] * (-offset)
            empty = tc.SArray(l, dtype=list.dtype)
            dest = tail.append(empty)
        else:
            l = [None] * (offset)
            empty = tc.SArray(l, dtype=list.dtype)
            head = list.head(count - offset)
            dest = empty.append(head)
        table.add_column(dest, column_name=dest_column, inplace=True)

    # 准备训练的数据
    def ready_train(self, table):
        if table.shape[0] < 10:
            print('table is too small for train')

        table.rename({'Close': 'p0'}, inplace=True)
        self.shift(table, -1, 'p0', 'Next')

        kl = ['Next']
        bounds = range(9)
        for n in bounds:
            key = 'p' + str(n + 1)
            kl.append(key)
            self.shift(table, -(n+1), 'p0', key)
            #检查这个shift是否正常

        result = table.dropna(columns=kl)

        rates = []
        for n in bounds:
            p_key = 'p{}'.format(n + 1)
            rates.append('rate{}'.format(n+1))

            result['diff{}'.format(n+1)] = result[['p0', p_key]].apply(lambda pair: float(pair['p0']) - float(pair[p_key]))
            result['rate{}'.format(n+1)] = result[['p0', p_key]].apply(lambda pair: float(pair['p0']) / float(pair[p_key]))
            result['sqr{}'.format(n+1)] = result[['p0', p_key]].apply(
                lambda pair: (pow(float(pair['p0']), 2) - pow(float(pair[p_key]), 2)) / float(pair[p_key]))

        return self.limit(result, rates)

    # 训练
    def train(self):
        table = cm.history_from_db(self.code)
        t = tc.SFrame(table)
        fix_t = self.ready_train(t)
        params = self.fix_parameters()
        model = tc.regression.create(fix_t, 'Next', params)
        model_file = u'./data/{code}.mlmodel'.format(code=self.code)
        print(model_file)
        model.export_coreml(model_file)

    # 准备计算结果
    def ready_generate(self, table):
        if table.shape[0] < 10:
            print('[ready_generate]table is too small, less than 10')
            return None

        dict = {}
        v_list = table['Close'].values
        current = float(v_list[0])
        dict['p0'] = current
        for n in range(10):
            prev = float(v_list[n+1])
            dict['p{}'.format(n+1)] = prev
            dict['diff{}'.format(n+1)] = current - prev
            dict['rate{}'.format(n+1)] = current / prev
            dict['sqr{}'.format(n+1)] = (pow(current,2) - pow(prev,2)) / prev

        frame = pd.DataFrame.from_dict(dict)
        return frame


    # 准备计算结果, 依照网络实时获得的数据
    def ready_generate_realtime(self, table, value):
        if table.shape[0] < 10:
            print('[ready_generate]table is too small, less than 10')
            return None

        dict = {}
        v_list = table['Close'].values
        current = value
        dict['p0'] = current
        for n in range(10):
            prev = float(v_list[n])
            dict['p{}'.format(n+1)] = prev
            dict['diff{}'.format(n+1)] = current - prev
            dict['rate{}'.format(n+1)] = current / prev
            dict['sqr{}'.format(n+1)] = (pow(current,2) - pow(prev,2)) / prev

        return json.dumps(dict)

    # 获得计算结果
    def generate(self):
        def run_turi(code, json_val):
            cmd = 'turi {model} \'{json}\''.format(model=code, json=json_val)
            print(cmd)
            cmd_result = os.popen(cmd)
            text = cmd_result.read()
            if text.startswith('{'):
                dict = json.loads(text)
                return dict
            return None

        table = cm.last_history_from_db(self.code, 10)
        json_val = self.ready_generate(table)


